


export class Utils {
    /*获取数据类型*/
    public static getType(any: any): string {
        const result = Object.prototype.toString.call(any).replace(/(^\[object\s)(\w+)(]$)/, function (_$0, _$1, $2) {
            return $2.toLowerCase();
        });
        return result;
    }
    /** isBoolean */
    public static isBoolean = (x: any): boolean => {
        return Utils.getType(x) === 'boolean';
    }
    /** isString */
    public static isString = (x: any): boolean => {
        return Utils.getType(x) === 'string';
    }
    /*isArray*/
    public static isArray = (x: any): boolean => {
        return Array.isArray(x);
    }
    /*isObject*/
    public static isObject = (x: any): boolean => {
        return Utils.getType(x) === 'object';
    }
    /*isFunction*/
    public static isFunction = (x: any): boolean => {
        return typeof x === 'function';
    }
    /*isNumber*/
    public static isNumber = (x: any): boolean => {
        return typeof x === 'number';
    }
    /*isUndefined*/
    public static isUndefined = (x: any): boolean => {
        return typeof x === 'undefined';
    }
    /*isNotUndefined*/
    public static isNotUndefined = (x: any): boolean => {
        return !Utils.isUndefined(x);
    }
    /* isNullObject 是否为空对象 空：false 非空：true */
    public static isNotNullObject = (x: any): boolean => {
        let result = false;
        let count = 0;
        if (Utils.isObject(x)) {
            for (const o in x) {
                if (x.hasOwnProperty(o)) {  // 建议加上判断,如果没有扩展对象属性可以不加
                    count++;
                }
            }
            result = !!count;
        } else {
            result = false;
        }
        return result;
    }
    public static isNullObject = (x: any): boolean => {
        return !Utils.isNotNullObject(x);
    }
    /*isNull*/
    public static isNull = (x: any): boolean => {
        return Utils.getType(x) === 'null';
    }
    /** 是否为空数据 */
    public static isEmpty = (value: any): boolean => {
        if (Utils.isObject(value) && Object.keys(value).length === 0) {
            return true;
        }
        if (Utils.isArray(value) && value.length === 0) {
            return true;
        }
        if (Utils.isString(value) && value.trim() === '') {
            return true;
        }
        if (Utils.isUndefined(value)) {
            return true;
        }
        if (Utils.isNull(value)) {
            return true;
        }
        return false;
    }
    public static isNotEmpty = (value: any): boolean => {
        return !Utils.isEmpty(value);
    }
    /** 一个字符串是否符合数字的模式 */
    public static isNumericString = (value: any) => {
        return /^\d+(\.\d+)?$/.test(value);
    }

    /**
     * 是否存在有效属性
     */
    public static isValidKey = (key: any, object: any): key is keyof typeof object => {
        return key in object;
    }

    public static getAttrValue = (key: string, object: any) => {
        return object[key];
    }

    /**
    * 取随机数
    * n:返回随机数个数
    *
    * @memberof UtilsProvider
    */
    public static getRandomChars = (n: number): string => {
        let result = '';
        const numberChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
        const lowerChars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
        const upperChars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
        // const markChars = ['~', '!', '@', '#', '$', '%', '^', '*', '_', '+'];
        const tempChars = [...lowerChars, ...numberChars, ...upperChars];

        for (let i = 0; i < n; i++) {
            const id = Math.ceil(Math.random() * (tempChars.length - 1));
            result += tempChars[id];
        }

        return result;
    }

    /** 计算字符串长度（包含中文，中文=2个长度） */
    public static countStringLength = (str: string): number => {
        const chineseRegex = /[\u4e00-\u9fa5]/;
        const arr = Array.from(str);
        let len = 0;
        arr.forEach(char => {
            if (chineseRegex.test(char)) {
                len = len + 2;
            } else {
                len = len + 1;
            }
        });
        return len;
    }
    /** 克隆 */
    public static clone<T>(obj: T): T {
        let result: any;
        if (Utils.getType(obj) === 'object') {
            result = {};
        } else if (Utils.getType(obj) === 'array') {
            result = [];
        } else {
            result = obj;
        }
        for (const key in obj) {
            if (Utils.getType(obj[key]) === 'object') {
                result[key] = Utils.clone(obj[key]);
            } else if (Utils.getType(obj[key]) === 'array') {
                result[key] = Utils.clone(obj[key]);
            } else {
                result[key] = obj[key];
            }
        }
        return result;
    }

    /**
     * jQuery param {a:1, b:2} => ?a=1&b=2
     */
    public static param = (a: { [key: string]: any }) => {
        const s: any[] = [];
        const add = function (k: any, v: any) {
            v = typeof v === 'function' ? v() : v;
            v = v === null ? '' : v === undefined ? '' : v;
            s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
        };
        const buildParams = function (prefix: any, obj: any) {
            if (prefix) {
                if (Array.isArray(obj)) {
                    for (let i = 0, len = obj.length; i < len; i++) {
                        buildParams(
                            prefix + '[' + (typeof obj[i] === 'object' && obj[i] ? i : '') + ']',
                            obj[i]
                        );
                    }
                } else if (String(obj) === '[object Object]') {
                    for (const key in obj) {
                        buildParams(prefix + '[' + key + ']', obj[key]);
                    }
                } else {
                    add(prefix, obj);
                }
            } else if (Array.isArray(obj)) {
                for (let i = 0, len = obj.length; i < len; i++) {
                    add(obj[i].name, obj[i].value);
                }
            } else {
                for (const key in obj) {
                    buildParams(key, obj[key]);
                }
            }
            return s;
        };
        return buildParams('', a).join('&');
    }

    /**
     * @description 一位数字 转换 两位数字 1 => 01
     * @author da
     * @param {number} n
     * @returns
     */
    public static to2digit(n: number): string {
        return ('00' + n).slice(-2);
    }

    /**
     * 等
     * @param delay 毫秒
     * @returns
     */
    public static sleep = (delay: number): Promise<void> => {
        return new Promise(resolve => setTimeout(resolve, delay));
    }


    /**
     * 获取url的search参数
     * @returns { [key: string]: string }
     */
    public static urlSearchQuery = (): { [key: string]: string } => {
        let search = window.location.search;
        search = search.replace(/\?/, '');
        const arr1 = search.split('&');
        const query: { [key: string]: string } = {};
        arr1.forEach((v) => {
            const arr2 = v.split('=');
            const key = arr2[0];
            const value = arr2[1];
            query[key] = value;
        });
        return query;
    }

    public static urlQuery = (key: string): string => {
        const query = Utils.urlSearchQuery();
        const value = query[key] || '';
        return value;
    }

    /**
     * 数字四舍五入 此处 n=2 好像没有生效
     */
    public static toFixed = (num: number | string, n = 2): string => {
        const strNum = num + '';
        let result = strNum;
        const reg = new RegExp(`(-?\\d+)\\.(\\d{${n}})(\\d)`);
        strNum.replace(reg, (_$0, $integer, $decimal, $token) => {
            // console.log(`字符串:${strNum}, 整数：${$integer},小数：${$decimal},关键数：${$token}`);
            // 五入
            if (+$token >= 5) {
                // result = `${$integer}.${+$decimal + 1}`;
                result = (+num).toFixed(2);
            } else { // 四舍
                result = `${$integer}.${$decimal}`;
            }
            return '';
        });
        if (isNaN(+result)) {
            result = '';
        }
        return result;
    };

    /** 数字转换字符串 1234567890 => 1,234,567,890 
     * 
    */
    public static moneyFormat = (num: number, prefix = '￥', n = 2): string => {
        // const arrNum: Array<string> = Utils.toFixed(num, n).split('.');  //此处 n=2 好像没有生效
        const arrNum: Array<string> = num.toFixed(n).split('.');
        // console.log(arrNum);
        const integer: string = arrNum[0];
        const decimal: string = arrNum[1] ? '.' + arrNum[1] : '';
        const integerRes = integer.replace(/(\d)(?=(\d{3})+$)/g, '$1,');
        return `${prefix}${integerRes}${decimal}`;
    }

    /** 字符串转换数字 1,234,567,890 => 1234567890 */
    public static moneyToNumber = (str: string): number => {
        return +str.replace(/,/g, '') || 0;
    }

    /** 数字范围 */
    public static rangeNumber = (val: number, max: number, min: number): number => {
        if (val > max) {
            return max;
        }
        if (val < min) {
            return min;
        }
        return val
    }

    /** 啥也不做 */
    public static noop = (...args: any[]) => {
        if (+new Date() === 1) {
            console.log(args);
        }
    }
    /** 啥也不做 */
    public static doNothing = Utils.noop;

}


